package com.gitee.cashzhang.test.basic.thread;

/**
 * @author Cash Zhang
 * @version v1.0
 * @since 2019/04/16 15:13
 */

import java.util.LinkedList;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 自定义大小的阻塞容器
 */
public class MyQueue {
  //1、初始化容器
  private final LinkedList<Object> list = new LinkedList<>();
  //2、定义计数器
  private AtomicInteger count = new AtomicInteger(0);
  //3、设定容器的上限和下限
  private final int minSize = 0;
  private final int maxSize;

  //4、构造器
  public MyQueue(int size) {
    this.maxSize = size;
  }

  //5、定义锁对象
  private final Object lock = new Object();

  //6、阻塞增加方法
  public void put(Object obj) {
    synchronized (lock) {
      while (count.get() == this.maxSize) {
        try {
          lock.wait();
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
      }
      //加入元素 计数器累加 唤醒取数线程可以取数
      list.add(obj);
      count.incrementAndGet();
      lock.notify();
      System.out.println("新增的元素:" + obj);
    }
  }

  public Object take() {
    Object result = null;
    synchronized (lock) {
      while (count.get() == this.minSize) {
        try {
          lock.wait();
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
      }
      //移除元素 计数器递减 唤醒添加的线程可以添加元素
      result = list.removeFirst();
      count.decrementAndGet();
      lock.notify();
    }
    return result;
  }

  public int getSize() {
    return this.count.get();
  }

  public static void main(String[] args) {
    final MyQueue myQueue = new MyQueue(5);
    myQueue.put("a");
    myQueue.put("b");
    myQueue.put("c");
    myQueue.put("d");
    myQueue.put("e");

    System.out.println("当前队列长度:" + myQueue.getSize());
    Thread t1 = new Thread(new Runnable() {
      @Override public void run() {
        myQueue.put("f");
        myQueue.put("g");
      }
    }, "t1");

    t1.start();

    Thread t2 = new Thread(new Runnable() {
      @Override public void run() {
        Object obj = myQueue.take();
        System.out.println("移除的元素为:"+obj);
        Object obj2 = myQueue.take();
        System.out.println("移除的元素为:"+obj2);
      }
    },"t2");

    try {
      TimeUnit.SECONDS.sleep(5);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }

    t2.start();
  }
}
